package me.bay.gt.java;

import java.util.Queue;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 本周作业：（必做）思考有多少种方式，在main函数启动一个新线程或线程池，
 * 异步运行一个方法，拿到这个方法的返回值后，退出主线程？
 * 写出你的方法，越多越好，提交到github。
 * <p>
 * 一个简单的代码参考：
 */
public class Main {

    public static void main(String[] args) throws Exception {
        method1();
        method2();
        method3();
        method4();
        method5();
        method6();
        method7();
        method8();
        method9();
        method10();
        method11();
    }

    private static int sum() {
        return fibo(36);
    }

    private static int fibo(int a) {
        if (a < 2)
            return 1;
        return fibo(a - 1) + fibo(a - 2);
    }

    private static void method1() {
        long start = System.currentTimeMillis();

        // 在这里创建一个线程或线程池，

        // 异步执行 下面方法
        int result = sum(); //这是得到的返回值

        // 确保  拿到result 并输出
        System.out.println("异步计算结果为：" + result);

        System.out.println("使用时间：" + (System.currentTimeMillis() - start) + " ms");

        // 然后退出main线程
    }

    private static void method2() throws Exception {
        long start = System.currentTimeMillis();

        // 在这里创建一个线程或线程池，
        ExecutorService executorService = Executors.newSingleThreadExecutor();

        // 异步执行 下面方法
        Future<Integer> futureResult = executorService.submit(Main::sum);

        int result = futureResult.get();
//        int result = sum(); //这是得到的返回值

        // 确保  拿到result 并输出
        System.out.println("异步计算结果为：" + result);

        System.out.println("使用时间：" + (System.currentTimeMillis() - start) + " ms");

        // 然后退出main线程
        executorService.shutdown();
    }

    private static void method3() throws InterruptedException {
        long start = System.currentTimeMillis();

        // 在这里创建一个线程或线程池，
        CountDownLatch countDownLatch = new CountDownLatch(1);
        AtomicInteger result = new AtomicInteger();
        Thread t = new Thread(() -> {
            result.set(sum());
            countDownLatch.countDown();
        });

        // 异步执行 下面方法
        t.start();
        countDownLatch.await();

        // 确保  拿到result 并输出
        System.out.println("异步计算结果为：" + result);

        System.out.println("使用时间：" + (System.currentTimeMillis() - start) + " ms");

        // 然后退出main线程
    }

    private static void method4() throws ExecutionException, InterruptedException {
        long start = System.currentTimeMillis();

        // 在这里创建一个线程或线程池，
        CyclicBarrier cyclicBarrier = new CyclicBarrier(1);
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            int tmp = sum();
            try {
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
            return tmp;
        });

        // 异步执行 下面方法
        int result = future.get();

        // 确保  拿到result 并输出
        System.out.println("异步计算结果为：" + result);

        System.out.println("使用时间：" + (System.currentTimeMillis() - start) + " ms");

        // 然后退出main线程
    }

    private static void method5() throws InterruptedException {
        long start = System.currentTimeMillis();
        final Object lock = new Object();

        // 在这里创建一个线程或线程池，
        AtomicInteger result = new AtomicInteger();
        Thread t = new Thread(() -> result.set(sum()));

        // 异步执行 下面方法
        t.start();
        TimeUnit.MILLISECONDS.sleep(200);

        // 确保  拿到result 并输出
        System.out.println("异步计算结果为：" + result);

        System.out.println("使用时间：" + (System.currentTimeMillis() - start) + " ms");

        // 然后退出main线程

    }

    private static void method6() throws InterruptedException {
        long start = System.currentTimeMillis();

        // 在这里创建一个线程或线程池，
        AtomicInteger result = new AtomicInteger();
        Thread t = new Thread(() -> result.set(sum()));

        // 异步执行 下面方法
        t.start();
        t.join();

        // 确保  拿到result 并输出
        System.out.println("异步计算结果为：" + result);

        System.out.println("使用时间：" + (System.currentTimeMillis() - start) + " ms");

        // 然后退出main线程
    }

    private static void method7() throws ExecutionException, InterruptedException {
        long start = System.currentTimeMillis();

        // 在这里创建一个线程或线程池，
        FutureTask<Integer> futureTask = new FutureTask<>(Main::sum);
        ExecutorService executorService = Executors.newSingleThreadExecutor();

        // 异步执行 下面方法
        executorService.execute(futureTask);
        int result = futureTask.get();

        // 确保  拿到result 并输出
        System.out.println("异步计算结果为：" + result);

        System.out.println("使用时间：" + (System.currentTimeMillis() - start) + " ms");

        // 然后退出main线程
        executorService.shutdown();
    }

    private static void method8() throws InterruptedException {
        long start = System.currentTimeMillis();
        ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(8);

        // 在这里创建一个线程或线程池，
        Thread t = new Thread(() -> queue.offer(sum()));
        // 异步执行 下面方法
        t.start();
        int result = queue.take();
        // 确保  拿到result 并输出
        System.out.println("异步计算结果为：" + result);

        System.out.println("使用时间：" + (System.currentTimeMillis() - start) + " ms");

        // 然后退出main线程
    }

    private static void method9() throws InterruptedException {
        long start = System.currentTimeMillis();
        final Object lock = new Object();
        AtomicInteger result = new AtomicInteger(0);

        Thread t = new Thread(() -> {
            synchronized (lock) {
                result.set(sum());
            }
        });

        t.start();
        Thread.sleep(1);
        synchronized (lock) {

        }
        // 确保  拿到result 并输出
        System.out.println("异步计算结果为：" + result);

        System.out.println("使用时间：" + (System.currentTimeMillis() - start) + " ms");

        // 然后退出main线程

    }
    private static void method10() throws InterruptedException {
        long start = System.currentTimeMillis();
        final Lock lock = new ReentrantLock(true);

        AtomicInteger result = new AtomicInteger(0);

        Thread t = new Thread(() -> {
            lock.lock();
            result.set(sum());
            lock.unlock();
        });

        t.start();
        Thread.sleep(1);
        lock.lock();
        lock.unlock();
        // 确保  拿到result 并输出
        System.out.println("异步计算结果为：" + result);

        System.out.println("使用时间：" + (System.currentTimeMillis() - start) + " ms");

        // 然后退出main线程

    }

    private static void method11() throws InterruptedException {
        long start = System.currentTimeMillis();

        AtomicInteger result = new AtomicInteger(0);

        Thread t = new Thread(() -> result.set(sum()));

        t.start();
        while (result.get() == 0) {
            Thread.sleep(1);
        }

        // 确保  拿到result 并输出
        System.out.println("异步计算结果为：" + result);

        System.out.println("使用时间：" + (System.currentTimeMillis() - start) + " ms");

        // 然后退出main线程
    }
}